﻿using FC.IService;
using FC.Data.ViewModels.Contests;
using System.Collections.Generic;
using System;
using FC.Data;
using System.Linq;
using FC.Utils;
using System.Data.Entity.Migrations;
using FC.Data.Models;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using System.Web;

namespace FC.Service
{
    public class ContestsService : IContestsService
    {
        /// <summary>
        /// 数据库上下文
        /// </summary>
        FCDbContext context = new FCDbContext();

        /// <summary>
        /// 每页显示的记录数
        /// </summary>
        static int PAGE_SIZE = 20;

        /// <summary>
        /// 根据题目状态获取题目状态样式
        /// </summary>
        /// <param name="state">题目状态</param>
        /// <returns></returns>
        private string GetStateCSS(string state)
        {
            string css = "";
            switch (state)
            {
                case "答案正确":
                    css = "success";
                    break;
                case "答案错误":
                    css = "warning";
                    break;
                case "格式错误":
                    css = "warning";
                    break;
                case "编译错误":
                    css = "danger";
                    break;
                case "运行超时":
                    css = "warning";
                    break;
                case "返回非零":
                    css = "danger";
                    break;
                case "多种错误":
                    css = "warning";
                    break;
                case "运行时错误":
                    css = "warning";
                    break;
                default:
                    css = "";
                    break;
            }
            return css;
        }

        /// <summary>
        /// 获取题目列表
        /// </summary>
        /// <param name="problemType">题目类型</param>
        /// <param name="page">页码</param>
        /// <returns></returns>
        public ProblemList GetProblemList(string problemType, int page)
        {
            ProblemList list = new ProblemList();

            var problems =
                from p in context.Problems
                where p.CollectionCode == problemType
                orderby p.No
                select new ProblemTitle()
                {
                    Id = p.Id,
                    Keyword = p.Keyword,
                    No = p.No,
                    PassCount = p.PassCount,
                    PassRate = p.PassRate,
                    State = "",
                    StateCSS = "",
                    SubmitCount  = p.SubmitCount,
                    Title = p.Title,
                };

            list.PageCount = (int)Math.Ceiling(problems.Count() / (double)PAGE_SIZE);
            list.Problems = problems.Skip((page - 1) * PAGE_SIZE).Take(PAGE_SIZE).ToList();
            list.Page = page;

            return list;
        }

        /// <summary>
        /// 获取题目内容
        /// </summary>
        /// <param name="problemType">题目类型</param>
        /// <param name="id">题目编号</param>
        /// <returns></returns>
        public ProblemContent GetProblemContent(string problemType, int id)
        {
            var problem =
                (from p in context.Problems
                where p.No == id && p.CollectionCode == problemType
                select new ProblemContent()
                {
                    Id = p.Id,
                    Convention = p.Convention,
                    Description = p.Description,
                    //Examples = p.Examples,
                    InputFormat = p.InputFormat,
                    No = id,
                    OutputFormat = p.OutputFormat,
                    Score = p.Score,
                    Tips = p.Tips,
                    Title = p.Title,
                    Author = p.Author,
                    Link =p.Link,
                    TestProcedure = p.TestProcedure,
                    CodeLengthRestriction = p.CodeLengthRestriction,
                    TimeLimit = p.TimeLimit,
                    MemoryLimit = p.MemoryLimit,
                    CollectionCode = p.CollectionCode,
                    Keyword = p.Keyword
                }).FirstOrDefault();


            if (problem != null)
            {
                var examples = (from e in context.ProblemExamples
                                where e.ProblemId == problem.Id
                                select e).ToList();

                problem.Examples = new List<ProblemExample>();

                foreach (var e in examples)
                {
                    problem.Examples.Add(e.Convert(new ProblemExample()));
                }
            }

            return problem;
        }

        /// <summary>
        /// 获取试题集列表
        /// </summary>
        /// <returns></returns>
        public List<ProblemCollection> GetCollections()
        {
            var list =
                from p in context.ProblemCollections
                select new ProblemCollection()
                {
                    Code = p.Code,
                    Name = p.Name,
                    State = p.State
                };
            return list.ToList();
        }

        /// <summary>
        /// 获取试题集名称
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public string GetCollectionName(string collection)
        {
            var name =
                from p in context.ProblemCollections
                where p.Code == collection
                select p.Name;
            return name.First();
        }

        /// <summary>
        /// 获取题目集信息
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public ProblemCollection GetCollection(string collection)
        {
            var pc =
                from p in context.ProblemCollections
                where p.Code == collection
                select p;
            ProblemCollection result = new ProblemCollection();
            pc.FirstOrDefault().Convert(result);
            return result;
        }

        /// <summary>
        /// 保存试题集
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Result SaveCollection(ProblemCollection model)
        {
            Result result = new Result() { state = "ok" };
            ProblemCollectionInfo pc = null; 
            if (string.IsNullOrWhiteSpace(model.Id))
            {
                pc = new ProblemCollectionInfo();
                model.Convert(pc);
                pc.Id = Guid.NewGuid().ToString();
            }
            else
            {
                pc = context.ProblemCollections.Where(p => p.Id == model.Id).FirstOrDefault();
                pc.Code = model.Code;
                pc.Name = model.Name;
                pc.State = model.State;
            }
            using (var transaction = context.Database.BeginTransaction())
            {
                context.ProblemCollections.AddOrUpdate(pc);
                try
                {
                    context.SaveChanges();
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    result.state = "error";
                    result.message = e.Message;
                    transaction.Rollback();
                }
            }

            return result;
        }

        /// <summary>
        /// 删除试题集
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public Result DeleteContest(string collection)
        {
            Result result = new Result() { state = "ok" };

            var pc = context.ProblemCollections.Where(p => p.Code == collection).FirstOrDefault();
            if(pc != null)
            {
                bool hasProblem = context.Problems.Any(p => p.CollectionCode == pc.Code);
                if (hasProblem)
                {
                    result.state = "error";
                    result.message = "该习题集下有题目，请先删除题目。";
                }
                else
                {
                    using (var transaction = context.Database.BeginTransaction())
                    {
                        context.ProblemCollections.Remove(pc);
                        try
                        {
                            context.SaveChanges();
                            transaction.Commit();
                        }
                        catch (Exception e)
                        {
                            result.state = "error";
                            result.message = e.Message;
                            transaction.Rollback();
                        }
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 保存题目信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Result SaveProblem(ProblemContent model)
        {
            Result result = new Result() { state = "ok" };

            ProblemInfo problem = new ProblemInfo();
            model.Convert(problem);

            if (string.IsNullOrWhiteSpace(problem.Id))
            {
                problem.Id = Guid.NewGuid().ToString();
            }

            List<ProblemExampleInfo> es = new List<ProblemExampleInfo>();
            foreach (var example in model.Examples)
            {
                ProblemExampleInfo e = new ProblemExampleInfo();
                example.Convert(e);
                if (string.IsNullOrWhiteSpace(e.ProblemId)) e.ProblemId = problem.Id;
                if (string.IsNullOrWhiteSpace(e.Id)) e.Id = Guid.NewGuid().ToString();
                es.Add(e);
            }

            using (var transaction = context.Database.BeginTransaction())
            {
                context.Problems.AddOrUpdate(problem);
                foreach (var example in es)
                {
                    context.ProblemExamples.AddOrUpdate(example);
                }
                try
                {
                    context.SaveChanges();
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    result.state = "error";
                    result.message = e.Message;
                    transaction.Rollback();
                }
            }

            return result;
        }

        /// <summary>
        /// 删除题目
        /// </summary>
        /// <param name="collection">试题集</param>
        /// <param name="id">题目编号</param>
        /// <returns></returns>
        public Result DeleteProblem(string collection, int? id)
        {
            Result result = new Result() { state = "ok" };

            using (var transaction = context.Database.BeginTransaction())
            {
                var problem = context.Problems.Where(p => p.No == id && p.CollectionCode == collection).FirstOrDefault();
                var list = context.ProblemExamples.Where(p => p.ProblemId == problem.Id).ToList();

                foreach (var item in list)
                {
                    context.ProblemExamples.Remove(item);
                }
                context.Problems.Remove(problem);
                try
                {
                    context.SaveChanges();
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    result.state = "error";
                    result.message = e.Message;
                    transaction.Rollback();
                }
            }

            return result;
        }

        /// <summary>
        /// 清空试题集
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public Result ClearCollection(string collection)
        {
            Result result = new Result() { state = "ok" };

            var problems = context.Problems.Where(p => p.CollectionCode == collection).ToList();
            var examples = context.ProblemExamples.Where(p=>p.Problem.CollectionCode == collection).ToList();

            using (var transaction = context.Database.BeginTransaction())
            {
                foreach (var item in examples)
                {
                    context.ProblemExamples.Remove(item);
                }
                foreach (var item in problems)
                {
                    context.Problems.Remove(item);
                }
                try
                {
                    context.SaveChanges();
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    result.state = "error";
                    result.message = e.Message;
                    transaction.Rollback();
                }
            }

            return result;
        }

        /// <summary>
        /// 全部导出
        /// </summary>
        /// <param name="collection"></param>
        public IWorkbook Export(string collection)
        {
            //获取题目信息
            var qp = context.Problems.AsQueryable();
            if (!string.IsNullOrWhiteSpace(collection)) qp = qp.Where(p => p.CollectionCode == collection);
            List<ProblemInfo> problems = qp.ToList();
            List<ExportProblemModel> problemList = new List<ExportProblemModel>();
            problems.Convert(problemList);

            //获取样例信息
            var qe = context.ProblemExamples.AsQueryable();
            if (!string.IsNullOrWhiteSpace(collection)) qe = qe.Where(p => p.Problem.CollectionCode == collection);
            List<ProblemExampleInfo> examples = qe.ToList();
            List<ExportExampleModel> exampleList = new List<ExportExampleModel>();
            examples.Convert(exampleList);

            IWorkbook workbook = new HSSFWorkbook();
            try
            {
                ISheet sheet1 = workbook.CreateSheet(problemList, "Problems");
                ISheet sheet2 = workbook.CreateSheet(exampleList, "Examples");

                //强制Excel重新计算表中所有的公式
                sheet1.ForceFormulaRecalculation = true;
                sheet2.ForceFormulaRecalculation = true;
            }
            catch (Exception e)
            {
                throw e;
            }

            return workbook;
        }

        /// <summary>
        /// 批量导入
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public Result Import(HttpPostedFileBase file)
        {
            Result result = new Result() { state = "ok" };
            using (var transaction = context.Database.BeginTransaction())
            {
                try
                {
                    IWorkbook workbook = file.CreateWorkbook();
                    ISheet sheet = workbook.GetSheet("Problems");
                    if (sheet != null)
                    {
                        List<ExportProblemModel> list = sheet.ToList<ExportProblemModel>();
                        foreach (var item in list)
                        {
                            ProblemInfo problem = new ProblemInfo()
                            {
                                CodeLengthRestriction = int.Parse(item.CodeLengthRestriction),
                                MemoryLimit = int.Parse(item.MemoryLimit),
                                No = int.Parse(item.No),
                                PassCount = int.Parse(item.PassCount),
                                PassRate = decimal.Parse(item.PassRate),
                                Score = int.Parse(item.Score),
                                SubmitCount = int.Parse(item.SubmitCount),
                                TimeLimit = int.Parse(item.TimeLimit),
                            };
                            item.Convert(problem);
                            context.Problems.Add(problem);
                        }
                    }
                    ISheet sheet2 = workbook.GetSheet("Examples");
                    if (sheet2 != null)
                    {
                        List<ExportExampleModel> list = sheet2.ToList<ExportExampleModel>();
                        foreach (var item in list)
                        {
                            ProblemExampleInfo example = new ProblemExampleInfo();
                            item.Convert(example);
                            context.ProblemExamples.Add(example);
                        }
                    }
                    context.SaveChanges();
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    result.message = e.Message;
                    result.state = "error";
                    transaction.Rollback();
                }
            }
            return result;
        }

        #region 之前的测试数据
        //if (problemType == "PAT")
        //    {
        //        problems = new List<ProblemTitle>()
        //        {
        //            new ProblemTitle() {
        //                Id = "",
        //                No=1001,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="亲爱的袁笛：",
        //                Keyword="PAT (Basic Level)",
        //                State="编译错误",
        //            },
        //            new ProblemTitle() {
        //                Id = "",
        //                No=1002,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="要开心哦",
        //                Keyword="要开心哦！",
        //                State="答案正确",
        //            }
        //            ,new ProblemTitle() {
        //                Id = "",
        //                No=1003,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="要想我哦，哈哈哈！",
        //                Keyword="要想我哦，哈哈哈",
        //                State="",
        //            }
        //            ,new ProblemTitle() {
        //                Id = "",
        //                No=1004,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="么么哒",
        //                Keyword="PAT (Basic Level)",
        //                State="",
        //            }
        //            ,new ProblemTitle() {
        //                Id = "",
        //                No=1005,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="爱你",
        //                Keyword="PAT (Basic Level)",
        //                State="答案错误",
        //            },
        //        };
        //    }
        //    else
        //    {
        //        problems = new List<ProblemTitle>()
        //        {
        //            new ProblemTitle() {
        //                Id = "",
        //                No=1001,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="Fibonacci数列",
        //                Keyword="入门 数列 取模",
        //                State="答案正确",
        //            },
        //            new ProblemTitle() {
        //                Id = "",
        //                No=1002,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="圆的面积",
        //                Keyword="入门 实数输出",
        //                State="答案错误",
        //            },
        //            new ProblemTitle() {
        //                Id = "",
        //                No=1003,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="序列求和",
        //                Keyword="入门 求和公式",
        //                State="",
        //            },
        //            new ProblemTitle() {
        //                Id = "",
        //                No=1004,
        //                PassCount=100,
        //                SubmitCount=200,
        //                PassRate=0.50M,
        //                Title="	A+B问题",
        //                Keyword="入门",
        //                State="编译错误",
        //            },
        //        };
        //    }

        //new ProblemContent()
        //{
        //    Convention = "1 <= n <= 1,000,000",
        //        Description = "Fibonacci数列的递推公式为：Fn=Fn-1+Fn-2，其中F1=F2=1。当n比较大时，Fn也非常大，现在我们想知道，Fn除以10007的余数是多少。",
        //        Examples = new List<ProblemExample>()
        //        {
        //            new ProblemExample()
        //            {
        //                InputExample = "10",
        //                OutputExample = "55",
        //            },
        //            new ProblemExample()
        //            {
        //                InputExample = "22",
        //                OutputExample = "7704",
        //            }
        //        },
        //        InputFormat = "输入包含一个整数n。",
        //        No = id,
        //        OutputFormat = "输出一行，包含一个整数，表示Fn除以10007的余数。",
        //        Score = 25,
        //        Tips = "在本题中，答案是要求Fn除以10007的余数，因此我们只要能算出这个余数即可，而不需要先计算出Fn的准确值，再将计算的结果除以10007取余数，直接计算余数往往比先算出原数再取余简单。",
        //        Title = "Fibonacci数列",
        //    };
        #endregion
    }
}
